package util.boyaa.recycle
{
	import flash.utils.Dictionary;
	import ghostcat.util.core.AbstractUtil;
	import org.as3commons.lang.ClassUtils;

	/**
	 * 对象回收模式
	 * 实现一套工厂方法和对象池机制
	 * @author henrylee
	 * 
	 */
	public class RecycleFactory implements IRecycleFactory
	{
		
		/**  
		       //参考该类  NormalRecycleFactory
			public class NormalRecycleFactory extends RecycleFactory 
			{
				
				private const MAX_LIMIT: int = 5;
				
				public function NormalRecycleFactory()
				{
					super();
					// 在这里注册该缓存池允许的类型和每个类型最大缓存个数
					m_warrantable[Recycleable]   =  MAX_LIMIT;
				}
				
				public function getInstanceList(type:Class): Array
				{
					return m_recyclableMap != null ? m_recyclableMap[type] : null;
				}
				
				public function get maxLimit(): int
				{
					return MAX_LIMIT;
				}
				
			}
		*/
		
		/** 允许缓存的类型 */
		protected var m_warrantable: Dictionary = new Dictionary();
		/** 分类回收对象 */		
		protected var m_recyclableMap: Dictionary = new Dictionary();
		
		/**
		 * 请实现一个该类的单例模式扩展然后使用
		 * 参考 NormalRecycleFactory.as
		 * 
		 */		
		public function RecycleFactory()
		{
			AbstractUtil.preventConstructor(this, RecycleFactory, "RecycleFactory is Abstract class!");
		}
		
		/**
		 * 释放所有缓存对象
		 */
		public function cleanup():void
		{
			var val: Vector.<IRecyclable>;
			for each(val in m_recyclableMap) {
				while (val.length)
					IRecyclable(val.pop()).dispose();
			}
		}
		
		/**
		 * 请通过可回收对象的recycle方法回收对象
		 * 直接调用该方法回收对象不是正确的使用方法
		 * @param recycleable
		 * 
		 */
		public function recycle(recycleable:IRecyclable): void
		{
			if (recycleable == null || recycleable.state != RecycleableVars.RECYCLE) return;
			
			var key: Class = checkValidInstance(recycleable);
			if (null == key) return;
			
			var objAry: Vector.<IRecyclable> = m_recyclableMap[key];
			if (null == objAry) {
				objAry = new Vector.<IRecyclable>();
				m_recyclableMap[key] = objAry;
			}
			
			if (objAry.length >= m_warrantable[key])
				recycleable.dispose();
			else if (objAry.indexOf(recycleable) == -1)
				objAry.push(recycleable);
		}
		
		/**
		 * 请求一个对象
		 * @param key  需求的对象类型
		 * @return 返回一个指定类型的对象
		 * 
		 */		
		public function getRecyclable(key:Class):IRecyclable
		{
			if (!checkValidClass(key)) return new key();
			
			var objAry: Vector.<IRecyclable> = m_recyclableMap[key];
			var obj: IRecyclable;
			if (null != objAry && objAry.length > 0)
				obj = objAry.pop();
			else
				obj = new key();
			
			obj.awake();
			obj.registerFactory(this);
			return obj;
		}
		
		/**
		 * 检验是否符合缓存池的条件
		 * @param _type
		 * 
		 */		
		protected function checkValidClass(_type:Class): Boolean
		{
			return null != m_warrantable[_type];
		}
		
		/**
		 * 检验是否符合缓存池的条件
		 * @param recycleable
		 * @return  返回符合条件的类型作为字典的key
		 * 
		 */		
		protected function checkValidInstance(recycleable: IRecyclable): Class
		{
			var paramClass: Class = ClassUtils.forInstance(recycleable);
			if (m_warrantable[paramClass]) return paramClass;
			return null;
		}

	}
}